package LogicModule

import (
	"errors"
	"gdbc/gdbc"
	"reflect"
	"frame/logger/HLogger"
	"database/sql"
)

/**
LOGIC注册模型
 */
type LogicModule struct {
	Name string
	Transaction bool
	Gdbcname string
	Logicfunc interface{}
}

var logicModules = make(map[string]LogicModule)


/**
注册一个logic
 */
func RegisterLogic(logic LogicModule)(bool,error){
	logicModules[logic.Name]=logic
	return true,nil
}
/**
获取一个logic
 */
func GetLogic(name string)(LogicModule,bool){
	logicmodule,found :=  logicModules[name]
	return logicmodule,found
}

func GetLogicModulesCount()(int){
	return len(logicModules)
}

func ProcessLogic(logicname string,txnContext HLogger.TxnContext,context map[string]interface{})(interface{},error){
	var logicModule,found = GetLogic(logicname)
	if(!found){
		return nil,errors.New("执行logic["+logicname+"]失败，该logic未注册")
	}
	var transaction bool = logicModule.Transaction
	var gdbcname string = logicModule.Gdbcname
	if(transaction){
		//如果需要事务
		db := gdbc.GetDB(gdbcname)
		tx,err:=db.Begin()
		if(err!=nil){
			return nil,errors.New("执行logic["+logicname+"]失败，启动事务失败["+err.Error()+"]")
		}
		//在上下文中添加事务
		context["TX"]=tx
	}

	//执行logic
	var logicresult interface{}
	//var err error
	logicfunc := reflect.ValueOf(logicModule.Logicfunc)
	if(logicfunc.Kind() != reflect.Func){
		return nil,errors.New("执行logic["+logicname+"]失败，logic的Logicfunc属性并非函数")
	}
	var callparam = make([]reflect.Value,0,5)

	//组装callparam
	callparam = append(callparam,reflect.ValueOf(&context))
	if(transaction) {
		var tx = context["TX"]
		callparam = append(callparam, reflect.ValueOf(tx))
	}
	callparam = append(callparam,reflect.ValueOf(txnContext))

	//函数调用
	var result []reflect.Value = logicfunc.Call(callparam)
	logicresult = result[0].Interface()
	err_interface := result[1].Interface()

	//提交事务或回滚事务
	if(transaction) {
		var tx *sql.Tx = context["TX"].(*sql.Tx)
		if(err_interface!=nil){
			tx.Rollback()
		}else{
			tx.Commit()
		}
		//删除上下文中的事务
		delete(context,"TX")
	}

	//组装结果

	if(err_interface!=nil){
		return logicresult,err_interface.(error)
	}

	//后续处理
	return logicresult,nil
}